package goldensubmarine.menCode.view.layers.pages.wear.wearSelector
{
	import com.greensock.easing.Expo;
	import com.greensock.easing.Quint;
	import com.greensock.TweenMax;
	import flash.display.Hit;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import goldensubmarine.menCode.events.UEventModel;
	import goldensubmarine.menCode.model.UModel;
	import msz.framework.events.PagesEvent;
	import msz.utils.MSZUtils;
	import net.badimon.five3D.display.Scene3D;
	import net.badimon.five3D.display.Sprite3D;
	import Singularity.Geom.Knot;
	import Singularity.Geom.PSpline3;
	import Singularity.Numeric.Consts;
	/**
	 * ...
	 * @author Bartłomiej JERZY
	 */
	public class Snake extends Sprite
	{
		private var NUM							:int = 0
		private const DIFF						:Number = 0.21
		private const DEAD						:Number = 0.4
		
		
		private var _scene						:Scene3D;
		private var _world						:Sprite3D;
		
		private var _data						:Object
		
		private var _center 					:Number = 0.5
		private var _left						:Number = 0
		private var _right						:Number = 1
		private var _spline						:PSpline3
		private var _splinePos					:Array = [	{x:-800,y:-400},
															{x:-700,y:-400},
															{x:-600,y:-400},
															{x:-40,y:0},
															{x:0,y:0},
															{x:40,y:0},
															{x:600,y:-400},
															{x:700,y:-400} ,
															{x:800,y:-400} ]
														
		private var _items						:Array = []					
		private var _displayList				:Array = []
		private var _knots						:Array = []
		private var _enabled					:Boolean = true
		
		private var _mid						:int
		private var _wheel						:Boolean = true
		private var _auto 						:Boolean = true
		private var _curr						:CarouselItem
		private var _currNum					:int 
		private var _currKnot					:Knot 

		private var _splineEdit					:Sprite = new Sprite();

		private var _speed						:Number = 0;
		private var _dataArray					:Array;
		
		private var _oldX						:Number = 0;
		private var _mouseIsDown				:Boolean;

		
		
		
		public function Snake($data:Object=null) 
		{
			if ($data) _data = $data
			
			addEventListener(Event.ADDED_TO_STAGE,init)
			
			_dataArray = MSZUtils.orderArray(_data);
			NUM = _dataArray.length
		}
		
		private function init(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,init)
			initSpline()
			initWorld()
			initSnake()
			initMouseMover()
			initEvents()
			initSplineEditor()
			UModel.addEventListener(UEventModel.MEN_CLOTHES_CHANGE, clothesChangeHandler)
			clothesChangeHandler()
		}
		
		//select CurrentClothes
		private function clothesChangeHandler(e:UEventModel = null):void {
			enableAllItems()
			if (UModel.level1Data && _dataArray.length) {
				for (var i:int = 0; i < UModel.clothes.length; i++) {
					checkClothesEnable(UModel.clothes[i].id)
				}
			}
			
		}
		
		private function checkClothesEnable($id:int):void{
			for (var i:int = 0; i < _dataArray.length; i++) {
				if (_dataArray[i].id == $id) {
					CarouselItem(_items[i]).selected = true
				}
			}
		}
		
		private function enableAllItems():void{
			for (var i:int = 0; i < _items.length; i++) {
				CarouselItem(_items[i]).selected = false
			}
		}
		
		private function initMouseMover():void{
			addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler)
		}
		
		private function mouseDownHandler(e:MouseEvent):void {
			_mouseIsDown = true
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler)
		}
		
		private function mouseUpHandler(e:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler)
			_mouseIsDown = false
		}
		
			
		private function oef(e:Event):void 
		{
			iph()
			if (_enabled) {
				position()
				render()
			}
			
		}

		
		private function iph() : void
		{
		  if (_mouseIsDown) {
			_speed = (stage.mouseX - _oldX) / 2400;
		  }  else {
			_speed *= 0.88;
		  }
		  _oldX = stage.mouseX;
		}
		
		
				
		private function initEvents():void
		{
			if (_items.length > 3) this.addEventListener(Event.ENTER_FRAME, oef);
		}
	
		private function initSnake():void
		{
			var _delay:int = 5
			
			var _num:int = 0
			for (var i:int = 0; i < _dataArray.length; i++) {
				_items[_num] = new CarouselItem(_dataArray[i]);
				_items[_num].y = CarouselItem.HEIGHT ;
				_items[_num].t = 0.5 + DIFF * _num - (NUM - 1) * DIFF / 2;
				_items[_num].addEventListener(PagesEvent.ON_CLEAR, onItemCleared);
				setAlpha(_items[_num]);
				
				_displayList[_num] = _items[_num];
					
				if (_items[_num].t >= 0 && _items[_num].t <= 1) {
					_world.addChild(_items[_num])
					
					setPosition(_items[_num])
					setAngle(_items[_num])
					
					_items[_num].visible = false
					
					TweenMax.to(_items[_num], 20, { z:_items[_num].z, autoAlpha:_items[_num].alpha, useFrames:true, startAt: { z:_items[_num].z + 500, autoAlpha:0 }, delay:_delay, ease:Expo.easeOut } )
					
					_delay += 3
				}
				_num++
			}
			
			TweenMax.delayedCall(_delay+10,initEvents,null,true)
			_curr = _items[0]
		}
		
		private function initWorld():void
		{
			stage.addEventListener(Event.RESIZE, resizeHandler)
			
			_scene = new Scene3D();
			_world = new Sprite3D()
			_world.z = 200
			
			_scene.ambientLightIntensity = .3
			
			_scene.addChild(_world);
			addChild(_scene);
			
			resizeHandler(null)
		}
		
		private function resizeHandler(e:Event):void 
		{
			_scene.x = _splineEdit.x = stage.stageWidth / 2;
			_scene.y = _splineEdit.y = stage.stageHeight / 2.9 //- 50;
		}
		
		private function initSpline():void
		{
			_spline = new PSpline3()
			for (var i:String in _splinePos) {
				_spline.addControlPoint(_splinePos[i].x, _splinePos[i].y)
			}
		}
		
		private function position():void {
			if (_speed < 0) {
				_currNum = _items.length - 1
				_items[_currNum].t += _speed
				if (_items[_currNum].t < 0.7) { _items[_currNum].t = 0.7;_speed = 0 }
			}else {
				_currNum = 0
				_items[_currNum].t += _speed
				if (_items[_currNum].t > .3){ _items[_currNum].t = 0.3 ; _speed = 0}
			}
			alignItems()
		}
				
		private function alignItems():void {			
			if (_currNum) {
				for (var i:int = _items.length-2; i >= 0; i--) {
					_items[i].t = _items[i + 1].t - DIFF
				}
			}else {
				for (var j:int = 1; j < _items.length; j++) {
					_items[j].t = _items[j - 1].t + DIFF
					
				}
			}
		}
		
		private function render():void {
		
			for (var i:int = 0; i < _items.length; i++) {
				if(_items[i].t >= _left && _items[i].t <= _right){
					setPosition(_items[i])
					setAngle(_items[i])
					if(!_world.contains(_items[i])) _world.addChild(_items[i])
				}else {
					if(_world.contains(_items[i])) _world.removeChild(_items[i])
				}
				
				setAlpha(_items[i])
			}
			_world.z = 200
			//_world.z += (Math.abs(_speed * 30000) - _world.z) / 20
			//_world.z += (Math.abs(_speed * 30000) - _world.z) / 100
			//trace(_world.z)
		}
		
		
		private function setAngle($item:CarouselItem):void {
			
			var _deltaX:Number  = _spline.getX($item.t-0.0001) - _spline.getX($item.t+0.0001)
			var _deltaZ:Number  = _spline.getY($item.t - 0.0001) - _spline.getY($item.t + 0.0001)
		
			var _angle:Number = 0
			if (_deltaX < 0 ){
				_angle = Math.atan2(_deltaZ, Math.abs(_deltaX))
			}else {
				_angle = Math.atan2(-_deltaZ, Math.abs(_deltaX))
			}
			$item.rotationY  = _angle * Consts.RAD_TO_DEG
		}
		
		private function setPosition($item:CarouselItem):void {
			$item.x = _spline.getX($item.t)
			$item.z = _spline.getY($item.t)
		}
		
		private function setAlpha($item:CarouselItem):void {
			if ( $item.t > _right-0.1 ) {
				$item.alpha = 1 - ($item.t - 0.9) * 10
			}else if ( $item.t  < _left+0.1 ) {
				$item.alpha = ($item.t)*10
			}else if ($item.t > _left && $item.t < _right){
				$item.alpha = 1
			}
		}
		
		public function hideAndClear():void {
			removeEventListener(Event.ENTER_FRAME, oef)
			removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler)
			UModel.removeEventListener(UEventModel.MEN_CLOTHES_CHANGE, clothesChangeHandler)
			TweenMax.killDelayedCallsTo(initEvents)
			_enabled = false
			
			for (var i:String in _items) {
				_items[i].hideAndClear()
			}
		}
		
				
		private function onItemCleared(e:PagesEvent):void 
		{
			NUM--
			if(!NUM) destroy()
		}
		

		public function destroy():void {
			
			stage.removeEventListener(Event.RESIZE, resizeHandler)
			
			_scene.removeChild(_world);
			removeChild(_scene);
			
			for (var i:String in _items) {
				if(_world.contains(_items[i])) _world.removeChild(_items[i])
			}
			
			_world = null		
			_scene = null		
			_items = null
			_displayList = null
			_spline = null
			
			dispatchEvent(new PagesEvent(PagesEvent.ON_CLEAR))
		}
		
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		private function initSplineEditor():void
		{
			_splineEdit = new Sprite()
			var _sh:Hit= new Hit()
			_spline.container = _sh
			
			_splineEdit.addChild(_sh)
			
			for (var i:String in _splinePos) {
				_knots[i] = new Knot(10,0xff0000)
				_knots[i].x = _splinePos[i].x
				_knots[i].y = _splinePos[i].y
				_knots[i].addEventListener(MouseEvent.MOUSE_DOWN, knotMouseDown, false, 0, true)
				_knots[i].id = i
				_splineEdit.addChild(_knots[i])
			}
			
			_spline.color = 0xff0000
			_spline.draw()
					
			
			addChild(_splineEdit)
		}
		
		
		private function knotMouseDown(e:MouseEvent):void 
		{
			stage.addEventListener(MouseEvent.MOUSE_MOVE,knotMouseMove,false,0,true)
			stage.addEventListener(MouseEvent.MOUSE_UP, knotMouseUp, false, 0, true)
			
			_currKnot = e.target as Knot
			_currKnot.startDrag()
		}
		private function knotMouseMove(e:MouseEvent):void 
		{
			_spline.moveControlPoint(_currKnot.id,_currKnot.x,_currKnot.y)
			_spline.draw()
		}
		private function knotMouseUp(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE,knotMouseMove)
			stage.removeEventListener(MouseEvent.MOUSE_UP, knotMouseUp)
			_currKnot.stopDrag()
			
			
			for (var i:String in _knots) {
				trace("{x:"+_knots[i].x+",y:"+_knots[i].y+"}")
			}
		}
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
	}

}